#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<malloc.h>

#include "ak_mem.h"
#include "font.h"

static char getBitFromData(char *dataStream, int i, int j, int height);
static void output_by_terminal(CharOBJ *_OBJ);

int ReadChineseChar(CharOBJ *_OBJ)
{ 
    unsigned char qh;
    unsigned char ql;
    unsigned long foffset;
    char filePath[32];
    int srcSize;
    int ret = 0;
    int height = _OBJ->charHeight;

    if(_OBJ->charType != CharType_Chinese)
    {
        printf("char type invalid!\n");
        return -1;
    }

    sprintf(filePath, "%s%dCHN.DZK", _OBJ->fontFilePrefix, _OBJ->charHeight);
    FILE *fp = fopen(filePath, "rb");
    if(fp == NULL)
    {
        printf("Open %s fail\n", filePath);
        return -1;
    }

    srcSize=height*height/8;

    qh=_OBJ->charPtr[0];
	ql=_OBJ->charPtr[1];
    if(qh<0xa1||ql<0xa1||ql==0xff||qh==0xff)
	{   	
        printf("invalid Chinese char! %d %d\n", ql, qh);  
	    return -1;  
	}    
	ql-=0xa1;  
	qh-=0xa1;  

	foffset=((unsigned long)94*qh+ql)*srcSize;	

    ret = fseek(fp, foffset, SEEK_SET);
    if(ret < 0)
    {
        printf("seek file fail %d\n", ret);
        return ret;
    }

    ret = fread(_OBJ->dataBuf, 1, srcSize, fp);
    if(ret <= 0)
    {
        printf("read file fail %d\n", ret);
        return ret;
    }
    // printf("read char %d success!\n", ret);

    ret = fclose(fp);
    if(ret != 0)
    {
        printf("close file fail![%d]\n", ret);
        return -1;
    }
}


int ReadAsciiChar(CharOBJ *_OBJ)
{
    char thisChar = *(_OBJ->charPtr);
    char filePath[32];
    int height = _OBJ->charHeight;
    int srcSize;
    int ret;

    /* 判断字符类型 */
    if(_OBJ->charType != CharType_Ascii)
    {
        printf("char type invalid!\n");
        return -1;
    }
    if(*(_OBJ->charPtr) >= 0x80)
    {
        printf("not a ascii char!\n");
        return -1;
    }

    sprintf(filePath, "%s%dASCII.DZK", _OBJ->fontFilePrefix, _OBJ->charHeight);
    FILE *fp = fopen(filePath, "rb");
    if(fp == NULL)
    {
        printf("Open %s fail\n", filePath);
        return -1;
    }

    srcSize=height*height/8;

    int foffset = thisChar*srcSize;
    ret = fseek(fp, foffset, SEEK_SET);
    if(ret < 0)
    {
        printf("seek file fail %d\n", ret);
        return ret;
    }

    ret = fread(_OBJ->dataBuf, 1, srcSize, fp);
    if(ret <= 0)
    {
        printf("read ASCII file fail %d\n", ret);
        return ret;
    }
    // printf("read char %d success!\n", ret);

    ret = fclose(fp);
    if(ret != 0)
    {
        printf("close file fail![%d]\n", ret);
        return -1;
    }
}

/**
 * @brief 从连续的数据中获取字模第i行，第j列的位
 * 
 * @param _OBJ 
 * @param i 
 * @param j 
 */
static char getBitFromData(char *dataStream, int i, int j, int height)
{
    int row_len = height/8;    //一行多少字节
    int col_num = j/8;
    int bit_num = j%8;

    return (dataStream[row_len*i+col_num]&(0x80>>bit_num))?1:0;
}

void output_by_terminal(CharOBJ *_OBJ)
{
    // int i, j;
    // int height, width;
    // height = _OBJ->height;
    // if(_OBJ->charType == CharType_Ascii)
    //     width = height/2;
    // else
    //     width = height;
    // for(i=0;i<height;i++)
    // {
    //     for(j=0;j<width;j++)
    //     {
    //         if(_OBJ->matBuff[j][i] != 0)
    //             printf("#");
    //         else
    //             printf(" ");
    //     }
    //     printf("\n");
    // }
}

int switchString2Rgba(StringOBJTypedef *_obj)
{
    char *thisChar;             //当前字符
    CharOBJ thisCharOBJ;        //当前字符对象
    int _width;                 //字符串宽度
    int charOffset = 0;         //字符偏移个数
    int strLen = 0;
    int i, j;
    int layer_size;

    if(_obj->stringHeight > srcHeightMax)
    {
        printf("string %s height out of max\n", _obj->string);
        return -1;
    }
    int height = _obj->stringHeight;

    /* 确定字符串大小 */
    strLen = strlen(_obj->string);
    _width=strLen*height/2;

    /* 确定RGBA图片大小 */
    layer_size = _width * height * 4;
    _obj->rgbaVarAddr = ak_mem_dma_alloc( 1, layer_size );                         //分配pmem内存
    int ret = ak_mem_dma_vaddr2paddr( _obj->rgbaVarAddr , ( unsigned long * )&_obj->srcLayer.phyaddr );    //获取rgba的dma物理地址
    if(ret < 0)
    {
        printf("String %s dma mem alloc fail!\n", _obj->string);
    }

    /* 建立二维数组 */
    struct RGBA *RGB_Buff[height];
    for(i=0;i<height;i++)
    {
        RGB_Buff[i] = _obj->rgbaVarAddr + i * _width * 4;
    }
    // printf("get RGBA buffer success\n");

    charOffset = 0;
    thisChar   = _obj->string + charOffset;  //赋第一个字符的地址
    while(charOffset < strLen)
    {
        int colOffset = charOffset*height/2;   //列偏移
        /* 若字符判定为汉字 */
        if(*thisChar > 0xA0)
        {
            int char_width = height;

            thisCharOBJ.charType = CharType_Chinese;
            thisCharOBJ.charHeight = height;
            thisCharOBJ.charPtr = thisChar;
            thisCharOBJ.fontFilePrefix = _obj->fontFilePrefix;
            ReadChineseChar(&thisCharOBJ);

            for(i=0;i<height;i++)
            {
                for(j=0;j<char_width;j++)
                {
                    int buff_j = j+colOffset;
                    if(getBitFromData(thisCharOBJ.dataBuf, i, j, height))
                    {
                        RGB_Buff[i][buff_j].Red   = _obj->stringRGB.Red;
                        RGB_Buff[i][buff_j].Green = _obj->stringRGB.Green;
                        RGB_Buff[i][buff_j].Blue  = _obj->stringRGB.Blue;
                        RGB_Buff[i][buff_j].Alpha = 255;
                    }
                    else
                    {
                        RGB_Buff[i][buff_j].Alpha = 0;
                    }
                }
            }
            charOffset += 2;
        }
        /* 若字符判定为ASCII */
        else if(*thisChar < 0x80)
        {
            int char_width = height/2;

            thisCharOBJ.charType = CharType_Ascii;
            thisCharOBJ.charHeight = _obj->stringHeight;
            thisCharOBJ.charPtr = thisChar;
            thisCharOBJ.fontFilePrefix = _obj->fontFilePrefix;
            if(ReadAsciiChar(&thisCharOBJ) < 0)
            {
                printf("Read ASCII fail\n");
                return -1;
            }

            for(i=0;i<height;i++)
            {
                for(j=0;j<char_width;j++)
                {
                    int buff_j = j+colOffset;
                    if(getBitFromData(thisCharOBJ.dataBuf, i, j, height))
                    {
                        RGB_Buff[i][buff_j].Red   = _obj->stringRGB.Red;
                        RGB_Buff[i][buff_j].Green = _obj->stringRGB.Green;
                        RGB_Buff[i][buff_j].Blue  = _obj->stringRGB.Blue;
                        RGB_Buff[i][buff_j].Alpha = 255;
                    }
                    else
                    {
                        RGB_Buff[i][buff_j].Alpha = 0;
                    }
                }
            }
            charOffset += 1;
        }
        else
        {
            printf("invalid char!%d\n", *thisChar);  
            return -1;  
        }
        thisChar = _obj->string + charOffset;
    }
    _obj->srcLayer.format_param = GP_FORMAT_ARGB8888;
    _obj->srcLayer.width  = _width;
    _obj->srcLayer.height = height;
    _obj->srcLayer.pos_left = 0;
    _obj->srcLayer.pos_top  = 0;
    _obj->srcLayer.pos_width  = _width;
    _obj->srcLayer.pos_height = height;
}

void freeStringMem(StringOBJTypedef *_obj)
{
    ak_mem_dma_free(_obj->rgbaVarAddr);
}

